package lottery

import (
	"sync"
	"time"

	"github.com/astaxie/beego/logs"

	"lottery/conf"
	"lottery/models"
)

type Manager struct {
	config *conf.ManagerConfig
	mux    *sync.RWMutex
	users  map[int64]*UserProc
}

func NewManager(config *conf.ManagerConfig) *Manager {
	return &Manager{
		config: config,
		mux:    new(sync.RWMutex),
		users:  make(map[int64]*UserProc),
	}
}

func (m *Manager) Run() {
	m.loadUsers()
	m.tickLoadUser()
}

func (m *Manager) LoadUser(user *models.User) {
	defer func() {
		if r := recover(); r != nil {
			m.mux.Lock()
			delete(m.users, user.Id)
			m.mux.Unlock()
		}
	}()

	// 更新用户数据
	// 提供给web接口实时调用
	userProc := NewUserProc(user)
	m.mux.Lock()
	m.users[user.Id] = userProc
	m.mux.Unlock()

	userProc.Run() // userProc 自理
	return
}

func (m *Manager) tickLoadUser() {
	tick := time.NewTicker(time.Duration(m.config.LoadTick) * time.Second)
	for t := range tick.C {
		logs.Notice("tick load user at %s", t.String())
		m.loadUsers()
	}
}

func (m *Manager) existsUser(user *models.User) bool {
	m.mux.RLock()
	_, ok := m.users[user.Id]
	m.mux.RUnlock()
	return ok
}

func (m *Manager) loadUsers() {
	users, err := models.GetAllUser()
	if err != nil {
		logs.Warn("get all user err:%s", err.Error())
		return
	}

	for _, user := range users {
		if !m.existsUser(user) {
			// 加载用户
			// 用户隔离
			go m.LoadUser(user)
		}
	}
}
